/*
 * Holds the JavaScript for content control of each section of the billboard.
 * Controls the fade in and fade out as well as calls appropriate response
 * handlers to render supported Google Visualizations.
 */

// Start section transitions as soon as the page is loaded.
window.onload = timer;

// Start initial timer count to 0 seconds.
var t = 0;
// All valid types the billboard supports.
var validTypes = ['pic', 'table', 'colchart', 'bhm'];

/*
 * Container to represent each section on the billboard.
 * Content is added to a Billboard Segment which is then
 * displayed in random order on the page.
 *
 * @param labelID Is the name given to the section.
 * @param contentID Is the div ID corresponding to the section.
 */
function billboardSegment(labelID, contentID) {
  
  /* Holds the name of the section. */
  this.labelID = labelID;
  
  /* Holds the div ID of the section. */
  this.contentID = contentID;
  
  /* Holds the labels of each content being added to the section. */
  this.label = new Array();
  
  /* Holds the content (either a URL or HTML) being added to the section. */
  this.content = new Array();
  
  /* Holds the types of each content being displayed. */
  /* Currently is pic|colchart|bhm|table */
  this.contentType = new Array();
  
  /* The name of the function to add content to a Billboard Segment. */
  this.addContent = addContent;
  
  /* The name of the function that is used to start the transitioning of a Billboard Segment. */
  this.start = startloop;
}

/*
 * Adds content to a Billboard Segment.
 *
 * @param type Is a string representing the type of content being displayed.
 * @param content Is a URL or HTML to a datasource or the HTML to be displayed.
 * @(optional param) label Is a string which labels section title, defaults to div ID of billboard segment.
 */
function addContent(type, content, label) {

  /* Base error checking if the user is adding null type or content */
  if (type == undefined) {
    alert("Invalid Add: Attempting to add content without a type to " + this.contentID + ".");
    error = true;
	return;
  }
  if (content == undefined) {
    alert("Invalid Add: No content is being added to " + this.contentID + ".");
    error = true;
    return;
  }
  
  /* Ensure the user is adding valid content types */
  var isValid = false;
  // Loop through all valid types, if the entered type does not exist,
  // then an error alert will pop-up.
  for (var i = 0; i < validTypes.length; i++) {
    if (validTypes[i] == type) {
      isValid = true;
	}
  }
  if ( !isValid ) {
    alert("Invalid Add: \"" + type + "\" is not a valid content type.");
    error = true;
    return;
  }

  // Add the content and type to the arrays in the billboardSegment class.
  this.content.push(content);
  this.contentType.push(type);

  // Default to the div ID if the label has not been set.
  // Add the label to the array in the billboard Segment class.
  if (label == undefined) {
    this.label.push(this.labelID);
  } else {
    this.label.push(label);
  }

}

/* 
 * Function called by the billboardSegment object 
 * to start looping through its contents.
 *
 * @param startIndex Is an array index of a content to start at.
 * @param displayTime Is a positive integer denoting how long a segment will display in seconds.
 */
function startloop(startIndex, displayTime) {
  loopContent(this.contentID, this.labelID, this.content, 
              this.contentType, this.label, startIndex, displayTime);
}

/* 
 * Loops through the content array and handles the calls to fade in and out.
 *
 * @param contentID Is the div ID of where the segment is being displayed.
 * @param labelID Is the default name of the section of the div ID.
 * @param contentArray Is an array of all content (URL or HTML) to be displayed.
 * @param contentTypeArray Is an array of all the types being displayed.
 * @param labelArray Is an array of strings holding the headers for each content to be displayed.
 * @param startingIndex Is an array index to grab content from contentArray.
 * @param displayTime IS a positive integer denoting how long a segment will display in seconds.
 */
function loopContent(contentID, labelID, contentArray, 
                     contentTypeArray, labelArray, startingIndex, displayTime) {
  // Loop for the amount of things in the content,
  // and start at the specified index.
  var size = contentArray.length;
  var i = startingIndex;

  // When the on-going timer and displayTime are multiples
  // of each other, it's time to transition.
  if ( (t % displayTime) == 0) {
	  
    // When the billboard has looped through all content.
    if (i >= size) {
      // Reset loop counter to 0 to start over.
      i = 0;
      
      // Continue the cycle of fading out and in, calling the next content to display.
      setFadeOut(100, labelID, contentID, contentArray[i], contentTypeArray[i], labelArray[i]);
      var fadeIn = function() {setFadeIn(0, labelID, contentID, contentArray[i-1], contentTypeArray[i-1], labelArray[i-1]);};
      
      // Set how long to wait to fade back in after fading out (in milliseconds).
      setTimeout(fadeIn, 1000);
      
      // Increment to queue up next content.
      i++;
    } else {
    // When there is still more to loop through.

      // Continue cycle of fading out and in, calling the next content to display.
      setFadeOut(100, labelID, contentID, contentArray[i], contentTypeArray[i], labelArray[i]);
      var fadeIn = function() {setFadeIn(0, labelID, contentID, contentArray[i-1], contentTypeArray[i-1], labelArray[i-1]);};
      
      // Set how long to wait to fade back in after fading out (in milliseconds).
      setTimeout(fadeIn, 1500);
      i++;
    }
  }

  // Recall the loop with the same parameters and cycle through the elements another time.
  var callFunction = function() { loopContent(contentID, labelID, contentArray, contentTypeArray, labelArray, i, displayTime); };
  setTimeout(callFunction, 1000);
  
}

/*
 * Timer that runs in the background that is used
 * to time when the sections would transition.
 * Increments the timer every second.
 */
function timer() {
  document.getElementById("timer").innerHTML = "Time Count:" + t;
  t++;
  setTimeout("timer()", 1000);
}

/*
 * Fade in function that controls the increase in opacity of the specified div tag.
 *
 * @param value Is the opacity level to be set on the divID.
 * @param labelID Is the default name of the section of the div ID.
 * @param divID Is the div element of the opacity being set.
 * @param content Is the URL or HTML being shown in the section.
 * @param contentType Is the type of content being shown in the section.
 * @param label Is the label being given as the section header for the content.
 */
function setFadeIn(value, labelID, divID, content, contentType, label) {
  // fadeIn variable to help reduce size of the setTimeout call.
  var fadeIn = function() {setFadeIn(value, labelID, divID, content, contentType, label);};
  // Fade the whole div tag to 100% opacity to be 100% viewable.
  if (value <= 100) {
    setOpacityValue(value, labelID, divID, content, contentType, label);
    value += 10;
    // Controls the speed of the fade in.
    setTimeout(fadeIn, 100); 
  }
}

/*
 * Fade out function that control the decrease of opacity of the specified div tag.
 *
 * @param value Is the opacity level to be set on the divID.
 * @param labelID Is the default name of the section of the div ID.
 * @param divID Is the div element of the opacity being set.
 * @param content Is the URL or HTML being shown in the section.
 * @param contentType Is the type of content being shown in the section.
 * @param label Is the label being given as the section header for the content.
 */
function setFadeOut(value, labelID, divID, content, contentType, label) {
  // fadeOut variable to help reduce size of the setTimeout call.
  var fadeOut = function() {setFadeOut(value, labelID, divID, content, contentType, label);};
  
  // Fade the whole div tag to 0% opacity, which will completely blank it out.
  if (value >= 0) {
    setOpacityValue(value, labelID, divID, content, contentType, label);
    value -= 10;
    // Controls the speed of the fade out.
    setTimeout(fadeOut, 100);
  }
}

/*
 * Sets the opacity of a div tag.  Once the tag fads out, calls appropriate handlers
 * to either display the next content in Billboard Segment.
 *
 * @param value Is the opacity level to be set on the divID.
 * @param labelID Is the default name of the section of the div ID.
 * @param divID Is the div element of the opacity being set.
 * @param content Is the URL or HTML being shown in the section.
 * @param contentType Is the type of content being shown in the section.
 * @param label Is the label being given as the section header for the content.
 */
function setOpacityValue(opacityValue, labelID, divID, content, contentType, label) {
  
  // First, set the opacity of both the label and content div so that both will
  // fade in and out as a single object.
  document.getElementById(labelID).style.opacity = opacityValue / 100;
  document.getElementById(divID).style.opacity = opacityValue / 100; 
  
  // When the opacity level reaches 0 (blanks out the section),
  // Update the label, and call appropriate handlers to display,
  // if any, visualizations.
  if(opacityValue == 0) {
    
    // Content for pictures is just the source file path to the picture 
    // relative to kukui-kup-billboard.html.  Here is where the image tag is built.
    if (contentType == 'pic') {
      document.getElementById(divID).innerHTML = '<img src=\'' + content + '\' />';
      document.getElementById(labelID).innerHTML = label;
    }
    // When the content calls for a table visualization.
    else if (contentType == 'table') {
      // Update the label.
      document.getElementById(labelID).innerHTML = label;
      
      // Query the data source and call appropriate handler.
      var query = new google.visualization.Query(content);
      query.send( function(response) { tableResponseHandler(response, divID); } );
    }
    // When the content calls for a column chart visualization.
    else if (contentType == 'colchart') {
      // Update the label.
      document.getElementById(labelID).innerHTML = label;
      
      // Query the data source and call appropriate handler.
      var query = new google.visualization.Query(content);

      // Default options array that takes off the legend and adds Watt Y axis title.
      var optionsArray = {};
      optionsArray['legend'] = 'none';
      optionsArray['is3D'] = false;
      optionsArray['titleY'] = 'Watts';
	  
      query.send( function(response) { colChartResponseHandler(response, divID, optionsArray); } );
    }
    // When the content calls for a BioHeatMap visualization.
    else if (contentType = 'bhm') {
      // Update the label.
      document.getElementById(labelID).innerHTML = label;

      // Query the data source and call appropriate handler.
      var query = new google.visualization.Query(content);

      // Default options array that removes pass through black and no border.
      // This is done so the BioHeatMap look contained in the div tag, and the
      // black does not interfere with the background.
      var optionsArray = {};
      optionsArray['passThroughBlack'] = false;
      optionsArray['drawBorder'] = false;

      query.send( function(response) { bhmResponseHandler(response, divID, optionsArray); } );
    }
  }
}

/*
 *Creates a sequence of numbers increasing by 1 for use with adding image content.
 *
 *@param start Is an integer which will be the start of the integer sequence.
 *@param end Is an integer which will be the end of the integer sequence.
 *@author Kendyll Doi, Paul Galiza, Edward Meyer, Jarrett Mizo
 */
function makeSequenceArray(start, end) {
  //initializes an array to hold the sequence and variables to hold start and end points.
  var sequence = new Array();
  var startPoint;
  var endPoint;
  
  //checks if the value given is a number and if not defaults to zero.
  if(!(typeof start == "number")){
    alert(typeof start == "number");
    start = 0;
  }
  if(!(typeof end == "number")){
    alert(typeof end == "number");
    end = 0;
  }
  
  //Insures the number is positive to match numbering convention.
  if (start < 0) {
    start = 0;
  }
  if (end < 0) {
    end = 0;
  }

   //Flips the start and end value if start is greater than end.
  if(start > end){
    startPoint = Math.floor(end);
    endPoint = Math.floor(start);
  } else {
    startPoint = Math.floor(start);
    endPoint = Math.floor(end);
  }
  
  //push numbers onto an array to make a incrementing array.
  if(startPoint != null && endPoint != null){
    //adds the values into an array from the start to the end using push.
    for(j = startPoint; j < (endPoint + 1); j++){
      sequence.push(j);
    }
    return sequence;
  } else {
    return null;
  }
}

/*
 *Shuffles the order of content within a BillBoardSegments contents and labels (which are stored in an array).
 *
 *@param section Is the BillboardSegment which will be shuffled in both content and labels.
 *@author Kendyll Doi, Paul Galiza, Edward Meyer, Jarrett Mizo
 */
function shuffle(section){
  //initializes temp variables to hold values.
  var changeContent;
  var changeLabel;
  var changeType;
  
  //will shuffle for all content,lables, and types in billboard segment
  for (i = 0; i < section.content.length; i++) {
    var j = Math.floor(Math.random() * section.content.length);
    //shuffles the Contents.
    changeContent = section.content[i];
    section.content[i] = section.content[j];
    section.content[j] = changeContent;
    //shuffles the Labels.
    changeLabel = section.label[i];
    section.label[i] = section.label[j];
    section.label[j] = changeLabel;
    // Shuffles the Types.
    changeType = section.contentType[i];
    section.contentType[i] = section.contentType[j];
    section.contentType[j] = changeType;
  }
}